package cc.ufinity.networkdiagnose.manager;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import cc.ufinity.networkdiagnose.util.HttpUtils;
import cc.ufinity.networkdiagnose.util.StringUtils;
import cc.ufinity.networkdiagnose.view.R;

import android.app.Activity;
import android.util.Log;

/**
 * Web登录及下线认证测试类
 * 
 * @author zhirong
 * 
 */
public final class WebAuthManager extends AbstractManager {

    private Activity ctx;
    private String wlanacip;
    private String wlanacname;
    private String wlanuserip;
    private String userName;
    private String pwd;
    private String logonsessid;

    private long startTime;
    private long endTime;
    private String loginUrl;
    private String loginSecUrl;
    private String logoutUrl;
    private String httpParamsWlancname;
    private String httpParamsWlanuserip;
    private String httpParamsWlanacip;
    private String httpParamsLogonSessinId;
    private static final String TAG = "WebAuth";
    private WebLoginHelper wh;

    // private static final String WLAN_CNAME_PARAMS = "wlanacname";
    // private static final String WLAN_USER_IP_PARAMS = "wlanuserip";
    // private static final String WLAN_ACIP = "wlanacip";
    // private static final String LOGIN_ACTION =
    // "https://221.176.1.140:443/do_login.php";
    // private static final String LOGIN_ACTION_SEC =
    // "https://221.176.1.140:443/do_login_second.php";
    // private static final String LOGOUT_ACTION =
    // "https://221.176.1.140:443/do_logout.php";

    public WebAuthManager(Activity context) {
        this.ctx = context;
        this.loginUrl = ctx.getResources().getString(R.string.login_url);
        this.loginSecUrl = ctx.getResources().getString(R.string.loginsec_url);
        this.logoutUrl = ctx.getResources().getString(R.string.logout_url);
        this.httpParamsWlancname = ctx.getResources().getString(R.string.httpParams_wlancname);
        this.httpParamsWlanacip = ctx.getResources().getString(R.string.httpParams_wlanacip);
        this.httpParamsWlanuserip = ctx.getResources().getString(R.string.httpParams_wlanuserip);
        this.httpParamsLogonSessinId = ctx.getResources().getString(R.string.httpParams_logonsessid);
        wh = new WebLoginHelper();

    }

    /**
     * 登录用户下线
     * 
     * @return TRUE or False
     */
    public boolean logout() {

        boolean success = false;
        HttpClient client = HttpUtils.getSSLHttpClient();
        try {
            HttpPost post = new HttpPost(logoutUrl);
            post.setEntity(new UrlEncodedFormEntity(setRequestParams()));
            HttpResponse response = client.execute(post);
            int sc = response.getStatusLine().getStatusCode();
            String content = EntityUtils.toString(response.getEntity());
            Log.d(TAG, content);
            if (sc == HttpStatus.SC_OK) {
                if (content.contains("下线成功")) {
                    success = true;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "下线认证出错：", e);
        } finally {
            client.getConnectionManager().shutdown();
        }
        return success;

        // return wh.CMCCLogout();
    }

    /**
     * 登录认证
     */
    public boolean auth(String url, String userName, String pwd) {

        this.userName = userName;
        this.pwd = pwd;
        boolean success = false;
        HttpClient client = HttpUtils.getSSLHttpClient();
        // HttpParams params = client.getParams();
        // params.setParameter(ClientPNames.HANDLE_REDIRECTS, false);
        HttpGet get = new HttpGet(url);
        try {
            // 由于CMCC的WEB登陆是采用redirect方式，先获得redirect后地址所携带的参数值
            HttpResponse response = client.execute(get);
            int sc = response.getStatusLine().getStatusCode();
            if ((sc == HttpStatus.SC_MOVED_TEMPORARILY) || sc == HttpStatus.SC_OK || (sc == HttpStatus.SC_MOVED_PERMANENTLY)
                    || (sc == HttpStatus.SC_SEE_OTHER) || (sc == HttpStatus.SC_TEMPORARY_REDIRECT))

            {
                String result = EntityUtils.toString(response.getEntity());
                // 解析各参数值
                Map<String, String> httpParams = parseLogonParams(result, "frame", "src");
                if(httpParams == null) return false;
                wlanacip = httpParams.get(this.httpParamsWlanacip);
                wlanacname = httpParams.get(this.httpParamsWlancname);
                wlanuserip = httpParams.get(this.httpParamsWlanuserip);
                HttpPost post = new HttpPost(this.loginUrl);
                post.setEntity(new UrlEncodedFormEntity(setRequestParams()));
                response = client.execute(post);
                sc = response.getStatusLine().getStatusCode();
                if (sc == HttpStatus.SC_OK) {
                    //
                    String content = EntityUtils.toString(response.getEntity());
                    Log.d(TAG, content);
                    if (content.contains("您好，您当前登录的用户已在线，是否继续操作")) {
                        String[] empties = result.split("\'");
                        for (int i = 0; i < empties.length; i++) {
                            if (empties[i].contains("window.location")) {
                                // next 2 url
                                url = empties[i + 1];
                                break;
                            }
                        }
                        post = new HttpPost(url);

                        // step 7 relogin
                        response = client.execute(post);
                        result = EntityUtils.toString(response.getEntity());
                        if (result.contains("用户登录成功")) {
                            Map<String, String> p = parseLogonParams(content, "frame", "src");
                            String sessionId = p.get(httpParamsLogonSessinId);
                            Log.d(TAG, sessionId);
                            this.setLogonsessid(sessionId);
                            success = true;
                        }
                    } else if (isLogin(content)) {
                        // 登录成功后获得Logonsessid
                        Map<String, String> p = parseLogonParams(content, "frame", "src");
                        String sessionId = p.get(httpParamsLogonSessinId);
                        Log.d(TAG, sessionId);
                        this.setLogonsessid(sessionId);
                        success = true;
                    }
                }
            }

        } catch (Exception e) {
            Log.e(TAG, "Web登陆认证发送错误：", e);
        } finally {
            client.getConnectionManager().shutdown();
        }
        return success;

        // return wh.CMCCLogin(userName, pwd);
    }

    /**
     * 如果用户在别处登录，注销别处会话再进行一次登录
     * 
     * @throws Exception
     */
    private boolean loginSec(HttpPost post, HttpClient client) throws Exception {
        boolean success = false;
        post = new HttpPost(this.loginSecUrl);
        post.setEntity(new UrlEncodedFormEntity(setRequestParams()));
        HttpResponse response = client.execute(post);
        int sc = response.getStatusLine().getStatusCode();
        if (sc == HttpStatus.SC_OK) {
            String content = EntityUtils.toString(response.getEntity());
            Log.e(TAG, content);
            success = true;
        }
        return success;
    }

    /**
     * 根据服务器端返回的页面内容进行解析，判断用户是否登录成功.
     * (如果中国移动程序遵循HTTP协议，直接返回HTTP状态码都无需进行页面解析，只能说明中国移动登录程序写的太烂.)
     * 
     * @param responseContent
     *            服务器返回的页面内容
     */
    private boolean isLogin(String responseContent) {
        boolean res = true;
        if (!StringUtils.isEmpty(responseContent)) {
            if (responseContent.contains("登录认证失败")) {
                res = false;
            }
        }
        return res;
    }

    /**
     * 根据服务器端返回的页面内容解析，判断用户账号是否在别处登录为在线状态。
     * 
     * @param response
     */
    private boolean isOnline(String response) {
        boolean res = false;
        if (!StringUtils.isEmpty(response)) {
            if (response.contains("当前登录的用户已在线")) {
                res = true;
            }
        }
        return res;
    }

    private Map<String, String> parseLogonParams(String content, String tag, String attr) {
        Map<String, String> httpParams = null;
        Document doc = Jsoup.parse(content);
        Element e = doc.select(tag).first();
        if (e != null) {
            String src = e.attr(attr);
            httpParams = StringUtils.parseURL(src);
        }
        return httpParams;
    }

    private String getAuthUrl(String content) {
        InputStream is = new ByteArrayInputStream(content.getBytes());
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));

        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                if (line.contains("http://221.130.132.1:8080")) {
                    int len = line.indexOf("http://");
                    int end = line.lastIndexOf('"');
                    line = line.substring(len, end);
                    sb.append(line);
                    Log.e(TAG, line);
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

    private List<NameValuePair> setRequestParams() {
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("staticusername", userName));
        params.add(new BasicNameValuePair("staticpassword", pwd));
        params.add(new BasicNameValuePair("loginmode", "static"));
        params.add(new BasicNameValuePair(httpParamsWlanacip, wlanacip));
        params.add(new BasicNameValuePair(httpParamsWlancname, wlanacname));
        params.add(new BasicNameValuePair(httpParamsWlanuserip, wlanuserip));
        params.add(new BasicNameValuePair("logouttype", "TYPESUBMIT"));
        if (!StringUtils.isEmpty(logonsessid)) {
            params.add(new BasicNameValuePair(httpParamsLogonSessinId, logonsessid));
        }
        return params;
    }

    public long getEndTime() {
        return endTime;
    }

    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    public String getLogonsessid() {
        return logonsessid;
    }

    public void setLogonsessid(String logonsessid) {
        this.logonsessid = logonsessid;
    }
}
